/////////////////////////////////////////////////////////////////////////////
/// \file CRC.c
/// \author Andre Mendonca
/// \brief
/// FRT TECNOLOGIA ELETRONICA LTDA<BR>
/// Av. Sul 3125F, Imbiribeira, CEP: 51.160 - 000<BR>
/// Recife, PE, Fone: 3081-1888<BR>
/// <BR>
/// Depto de Projeto & Desenvolvimento.<BR>
/// Divisao de Desenvolvimento de Software Embarcado<BR>
/// <BR>
/// Data de Criacao do Modulo: 11/11/2008 10:14:07
/// <BR>
/// Descricao: M&oacute;dulo respons&aacute;vel pelo c&aacute;lculo de CRC16-CCITT.
/////////////////////////////////////////////////////////////////////////////

#include "target.h"
#include "CRC.h"

U16 tableNibble[16] =
{
	0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
	0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF
};

/////////////////////////////////////////////////////////////////////////////
/// \brief O valor inicial do CRC16 CCITT: 0xFFFF � atribu�do na vari�vel local.
void service_CRC16Init(U16 *crc16)
{
	(*crc16) = CRC_INIT_VALUE;
}
/////////////////////////////////////////////////////////////////////////////
/// \brief Recebe um byte e acumula no CRC16 atual, apenas o HIGH NIBBLE do byte.
///
/// \param byte BYTE a ser acumulado no CRC16 atual
///
/////////////////////////////////////////////////////////////////////////////
void service_CRC16UpdateNibble(U8 byte, U16 *crc16)
{
	U8 index;

	index = ((unsigned char)((*crc16) >> 12)) ^ (byte >> 4);
	(*crc16) = ((*crc16) << 4) ^ tableNibble[index];
}

/////////////////////////////////////////////////////////////////////////////
/// \brief Recebe um byte e acumula no CRC16 atual. A rotina executa a
///			fun&ccedil;&atilde;o dela acumulando o HIGH_NIBBLE e em seguida o LOW_NIBBLE.
///			Na hora de enviar o CRC16-CCITT envia-se o HIGH e depois o LOW
///			NIBBLE nessa ordem o CRC16 n&atilde;o bater&aacute; no lado da recep&ccedil;&atilde;o.
///
///
/// \param byte BYTE que atualizar&aacute; do CRC16 atual
///
/////////////////////////////////////////////////////////////////////////////
void service_CRC16UpdateByte(U8 byte, U16 *crc16)
{
	service_CRC16UpdateNibble(byte, crc16);
	service_CRC16UpdateNibble(byte << 4, crc16);
}

/////////////////////////////////////////////////////////////////////////////
/// \brief Recebe um stream e os acumula no CRC16 atual
///
/// \param bytes Stream que atualizar� o CRC16 atual tamanho Tamanho do stream
///
/////////////////////////////////////////////////////////////////////////////
void service_CRC16UpdateStream(U8 * bytes, U16 tamanho, U16 *crc16)
{
	U16 index;

	for (index = 0; index < tamanho; index++) {
		service_CRC16UpdateByte(bytes[index], crc16);
	}
}
